package com.agri.controller;
import com.agri.dto.LoginRequestDTO;
import com.agri.dto.LoginResponseDTO;
import com.agri.dto.RegisterRequestDTO;
import com.agri.entity.User;
import com.agri.entity.UserRole;
import com.agri.mapper.UserMapper;
import com.agri.mapper.UserRoleMapper;
import com.agri.result.Result;
import com.agri.utils.EncryptUtil;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.crypto.SecretKey;
import javax.validation.Valid;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/public")
public class AuthController {

    @Value("${jwt.secret}")
    private String jwtSecret;

    @Value("${jwt.expiration}")
    private Long jwtExpiration;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @PostMapping("/register")
    public Result<?> register(@Valid @RequestBody RegisterRequestDTO registerRequest) {
        log.info("=== 用户注册开始 ===");
        log.info("注册用户名: {}", registerRequest.getUsername());

        try {
            // 检查用户名是否已存在
            User existingUser = userMapper.selectByUsername(registerRequest.getUsername());
            if (existingUser != null) {
                log.warn("注册失败: 用户名已存在 - {}", registerRequest.getUsername());
                return Result.fail("用户名已存在");
            }

            // 创建新用户
            User newUser = new User();
            newUser.setUsername(registerRequest.getUsername());
            newUser.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
            newUser.setRealName(registerRequest.getRealName());

            // 加密敏感信息
            newUser.setPhone(EncryptUtil.encrypt(registerRequest.getPhone()));
            newUser.setIdCard(EncryptUtil.encrypt(registerRequest.getIdCard()));

            newUser.setEmail(registerRequest.getEmail());
            newUser.setStatus(1); // 启用状态

            // 插入用户到数据库
            int result = userMapper.insert(newUser);
            if (result <= 0) {
                log.error("注册失败: 数据库插入失败 - {}", registerRequest.getUsername());
                return Result.fail("注册失败，请稍后重试");
            }

            // 为用户分配默认角色 (ROLE_USER)
            UserRole userRole = new UserRole();
            userRole.setUserId(newUser.getId());
            userRole.setRoleId(2L); // ROLE_USER的角色ID为2
            userRoleMapper.insert(userRole);

            log.info("注册成功: 用户 {} 已创建", registerRequest.getUsername());
            return Result.success("注册成功");

        } catch (Exception e) {
            log.error("注册异常: {}", e.getMessage(), e);
            return Result.fail("注册失败，请稍后重试");
        }
    }

    @PostMapping("/login")
    public Result<?> login(@Valid @RequestBody LoginRequestDTO loginRequest) {
        log.info("=== 登录请求开始 ===");
        log.info("用户名: {}", loginRequest.getUsername());

        try {
            // 验证用户凭据
            log.debug("正在加载用户详情...");
            UserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsername());
            log.debug("用户详情加载成功: {}", userDetails.getUsername());

            log.debug("正在验证密码...");
            boolean passwordMatches = passwordEncoder.matches(loginRequest.getPassword(), userDetails.getPassword());
            log.debug("密码匹配结果: {}", passwordMatches);

            if (!passwordMatches) {
                log.warn("登录失败: 密码不匹配 - 用户: {}", loginRequest.getUsername());
                return Result.fail("用户名或密码错误");
            }

            // 获取用户角色
            List<String> roles = userDetails.getAuthorities().stream()
                    .map(GrantedAuthority::getAuthority)
                    .collect(Collectors.toList());
            log.debug("用户角色: {}", roles);

            // 生成JWT token
            log.debug("正在生成JWT token...");
            SecretKey key = Keys.hmacShaKeyFor(jwtSecret.getBytes(StandardCharsets.UTF_8));
            String token = Jwts.builder()
                    .setSubject(loginRequest.getUsername())
                    .claim("roles", roles)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + jwtExpiration))
                .signWith(key)
                .compact();
            log.debug("Token生成成功");

            // 获取用户详细信息用于返回
            User user = userMapper.selectUserWithRolesByUsername(loginRequest.getUsername());
            LoginResponseDTO response = new LoginResponseDTO(
                token,
                user.getUsername(),
                roles,
                user.getRealName()
            );

            log.info("=== 登录成功 ===");
            return Result.success(response);
        } catch (Exception e) {
            log.error("登录异常: {}", e.getMessage(), e);
            return Result.fail("用户名或密码错误");
        }
    }

    public static class LoginRequest {
        private String username;
        private String password;

        // getters and setters
        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }
    }
}
